package com.zxt.content.common.client;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.PutObjectRequest;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.UUID;

/**
 * @author zxt
 */
@Service
@AllArgsConstructor
@Slf4j
@NoArgsConstructor
public class OssClient {

    @Value("${storage.aliyun.url:}")
    private String url;

    @Value("${storage.aliyun.endpoint:}")
    private String endpoint;

    @Value("${storage.aliyun.bucketName:}")
    private String bucket;

    @Value("${storage.aliyun.accessKeyId:}")
    private String accessId;

    @Value("${storage.aliyun.accessKeySecret:}")
    private String secretKey;

    /**
     * oss图片存储的目录
     */
    private final String imageDirectory = "content/image/";
    /**
     * oss文本存储的目录
     */
    private final String txtDirectory = "content/txt/";
    /**
     * oss语音存储的目录
     */
    private final String imageVoice = "content/voice/";

    public String uploadImage(MultipartFile multipartFile)
            throws OSSException, ClientException {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(this.endpoint, this.accessId, this.secretKey);
        try {
            if (multipartFile.getSize() != 0 && !"".equals(multipartFile.getName())) {
                // getInputStream()返回一个InputStream以从中读取文件的内容。通过此方法就可以获取到流
                InputStream multipartFileInputStream = multipartFile.getInputStream();
                //拼接上传后的目录
                StringBuilder builder = new StringBuilder(imageDirectory);
                builder.append(LocalDate.now().toString());
                builder.append("/");
                builder.append(UUID.randomUUID().toString().replaceAll("-", ""));
                builder.append(".png");
                String fileUrl = builder.toString();
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, fileUrl, multipartFileInputStream);
                ossClient.putObject(putObjectRequest);
                return url + fileUrl;
            }
        } catch (Exception e) {
            log.error("上传oss导入图片失败:{}", e);
        } finally {
            // 关闭流
            ossClient.shutdown();
        }
        return null;
    }

    public String uploadTxt(MultipartFile multipartFile)
            throws OSSException, ClientException {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(this.endpoint, this.accessId, this.secretKey);
        try {
            if (multipartFile.getSize() != 0 && !"".equals(multipartFile.getName())) {
                // getInputStream()返回一个InputStream以从中读取文件的内容。通过此方法就可以获取到流
                InputStream multipartFileInputStream = multipartFile.getInputStream();
                //拼接上传后的目录
                StringBuilder builder = new StringBuilder(txtDirectory);
                builder.append(LocalDate.now().toString());
                builder.append("/");
                builder.append(UUID.randomUUID().toString().replaceAll("-", ""));
                builder.append(".txt");
                String fileUrl = builder.toString();
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, fileUrl, multipartFileInputStream);
                ossClient.putObject(putObjectRequest);
                return url + fileUrl;
            }
        } catch (Exception e) {
            log.error("上传oss导入图片失败:{}", e);
        } finally {
            // 关闭流
            ossClient.shutdown();
        }
        return null;
    }

    public String uploadVoice(MultipartFile multipartFile) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(this.endpoint, this.accessId, this.secretKey);
        try {
            if (multipartFile.getSize() != 0 && !"".equals(multipartFile.getName())) {
                // getInputStream()返回一个InputStream以从中读取文件的内容。通过此方法就可以获取到流
                InputStream multipartFileInputStream = multipartFile.getInputStream();
                //拼接上传后的目录
                StringBuilder builder = new StringBuilder(imageVoice);
                builder.append(LocalDate.now().toString());
                builder.append("/");
                builder.append(UUID.randomUUID().toString().replaceAll("-", ""));
                builder.append(".mp3");
                String fileUrl = builder.toString();
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, fileUrl, multipartFileInputStream);
                ossClient.putObject(putObjectRequest);
                return url + fileUrl;
            }
        } catch (Exception e) {
            log.error("上传oss导入语音失败:{}", e);
        } finally {
            // 关闭流
            ossClient.shutdown();
        }
        return null;
    }

    public String downloadFile(String fileUrl) {
        fileUrl = fileUrl.replace(url, "");
        //本地存储目录
        String directoryPath = "./ossFile/" + (LocalDate.now().toString());
        File directory = new File(directoryPath);
        //如果没有该目录进行创建
        directory.mkdirs();
        String pathName = directoryPath + fileUrl.substring(fileUrl.lastIndexOf("/"));

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(this.endpoint, this.accessId, this.secretKey);

        try {
            // 下载Object到本地文件，并保存到指定的本地路径中。如果指定的本地文件存在会覆盖，不存在则新建。
            // 如果未指定本地路径，则下载后的文件默认保存到示例程序所属项目对应本地路径中。
            ossClient.getObject(new GetObjectRequest(this.bucket, fileUrl), new File(pathName));
            return pathName;
        } catch (Exception e) {
            log.error("下载oss导入文件失败:{}", e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return directoryPath;
    }
}
